package com.stars.module.code.service.impl;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.stars.base.constants.CommonNumberConstants;
import com.stars.base.constants.RedisConstants;
import com.stars.base.entity.CommonDTO;
import com.stars.base.entity.Result;
import com.stars.base.entity.TreeNode;
import com.stars.module.code.entity.StarCode;
import com.stars.module.code.mapper.CodeMapper;
import com.stars.module.code.service.CodeService;
import com.stars.util.cache.CacheUtil;
import com.stars.util.common.DevelopKit;
import com.stars.util.tree.TreeNodeUtil;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author : Rocks
 * @version : 1.0
 * @date : 2022/10/28 23:31
 * @description : 数据代码服务实现类
 */
@Service
public class CodeServiceImpl implements CodeService {

    private final CacheUtil cacheUtil;
    private final CodeMapper codeMapper;

    public CodeServiceImpl(CacheUtil cacheUtil, CodeMapper codeMapper) {
        this.cacheUtil = cacheUtil;
        this.codeMapper = codeMapper;
    }

    @Override
    public JSONArray loadCodeTree() {

        LambdaQueryWrapper<StarCode> wrapper = new LambdaQueryWrapper<>();

        wrapper.eq(StarCode::getType,1).or().eq(StarCode::getType,2);

        JSONArray array = new JSONArray();

        List<StarCode> codeList = Optional.ofNullable(codeMapper.selectList(wrapper)).orElse(Collections.emptyList());

        List<TreeNode> treeNodes = codeList.stream().map(code -> {
            TreeNode node = new TreeNode(code.getId(),code.getCodeText(),code.getFid());

            JSONObject attr = new JSONObject();
            attr.put("type", code.getType());

            node.setAttr(attr);

            return node;
        }).collect(Collectors.toList());

        TreeNode root = new TreeNode(CommonNumberConstants.ZERO_STR,"代码管理",CommonNumberConstants.MINUS_ONE_STR);

        array.add(TreeNodeUtil.merge(root,treeNodes).toJSON());

        return array;
    }

    @Override
    public JSONObject loadCodeListByFid(CommonDTO dto) {

        Page<StarCode> page = Page.of(dto.getCurrent(), dto.getPageSize());

        LambdaQueryWrapper<StarCode> wrapper = new LambdaQueryWrapper<>();

        wrapper.eq(StarCode::getFid,dto.getFid()).and(
            query -> query.like(StarCode::getCodeText,dto.getSearch())
                    .or()
                    .like(StarCode::getCodeValue,dto.getSearch())
        );

        wrapper.orderByAsc(StarCode::getShowOrder);

        JSONObject result = new JSONObject();

        Page<StarCode> starCodePage = codeMapper.selectPage(page, wrapper);

        result.put("list",starCodePage.getRecords());
        result.put("total",starCodePage.getTotal());

        return result;
    }

    @Override
    public StarCode loadCodeById(String id) {
        return codeMapper.selectById(id);
    }

    @Override
    public Result removeCode(String codeId, String type) {

        if(CommonNumberConstants.ONE_STR.equals(type)){
            LambdaQueryWrapper<StarCode> query = new LambdaQueryWrapper<>();
            query.eq(StarCode::getFid,codeId);

            //删除代码目录或者分类,需要线校验是否有子级
            if(codeMapper.exists(query)){
                return Result.error("当前文件夹存在有效子级，请删除子级后重试！");
            }
        }

        return codeMapper.deleteById(codeId)>0?Result.success():Result.error();
    }

    @Override
    public Result saveOrUpdateCode(StarCode code) {

        LambdaQueryWrapper<StarCode> query = new LambdaQueryWrapper<>();

        query.eq(StarCode::getCodeValue,code.getCodeValue());
        query.eq(StarCode::getFid,code.getFid());
        query.ne(StarCode::getId,code.getId());

        if(codeMapper.exists(query)){
            return Result.error("同级目录下存在重复代码值！");
        }

        if(code.getType().equals(CommonNumberConstants.TWO_STR)) {

            query = new LambdaQueryWrapper<>();
            query.eq(StarCode::getFid,code.getId());

            if(codeMapper.exists(query)) {
                return Result.error("当前目录下存在有效代码，请删除后修改代码类型！");
            }
        }

        if(StringUtils.hasLength(code.getId())) {
            // 更新操作
            return codeMapper.updateById(code) > 0 ? Result.success():Result.error();
        } else {
            // 新增操作
            code.setId(DevelopKit.generateUUID());
            DevelopKit.setBaseInfo(code);
            return codeMapper.insert(code) > 0 ? Result.success():Result.error();
        }
    }

    @Override
    public int getMaxIndex(String fid) {

        QueryWrapper<StarCode> queryWrapper = new QueryWrapper<>();

        queryWrapper.lambda().eq(StarCode::getFid,fid);
        queryWrapper.select("MAX(SHOWORDER) AS SHOWORDER");

        StarCode starCode = codeMapper.selectOne(queryWrapper);

        return starCode!=null?starCode.getShowOrder():0;
    }

    @Override
    public JSONArray getCode(String fid) {
        JSONArray array = new JSONArray();

        List<StarCode> starList = cacheUtil.getValueByList(false,RedisConstants.STAR_CODE_PREFIX + fid, StarCode.class);

        if (starList == null || starList.isEmpty()) {

            LambdaQueryWrapper<StarCode> query = new LambdaQueryWrapper<>();

            query.eq(StarCode::getFid,fid);
            query.orderByAsc(StarCode::getShowOrder);

            starList = Optional.ofNullable(codeMapper.selectList(query)).orElse(Collections.emptyList());

            cacheUtil.setValue(false, RedisConstants.STAR_CODE_PREFIX + fid, starList);

        }

        starList.forEach(code -> {
            JSONObject obj = new JSONObject();

            obj.put("label",code.getCodeText());
            obj.put("value",code.getCodeValue());

            array.add(obj);
        });

        return array;
    }

    @Override
    public JSONArray getCodeByTree(String fids) {

        if(!StringUtils.hasLength(fids)){
            return new JSONArray();
        }

        String[] fidArr = fids.split(",");

        JSONArray array = new JSONArray();

        for(String fid : fidArr) {

            LambdaQueryWrapper<StarCode> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(StarCode::getId,fid);

            StarCode starCode = codeMapper.selectOne(wrapper);

            wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(StarCode::getFid,fid);

            List<StarCode> codeList = codeMapper.selectList(wrapper);

            List<TreeNode> treeNodes = new ArrayList<>();

            for(StarCode code : codeList){
                TreeNode node = new TreeNode();
                node.setValue(code.getId());
                node.setLabel(code.getCodeText());
                node.setpId(code.getFid());

                JSONObject attr = new JSONObject();
                attr.put("type", code.getType());

                node.setAttr(attr);

                treeNodes.add(node);

            }

            TreeNode root = new TreeNode(fid,starCode.getCodeText(),starCode.getFid());

            array.add(TreeNodeUtil.merge(root,treeNodes).toJSON());
        }

        return array;
    }

    @Override
    public JSONArray getCodeGroupTree() {
        LambdaQueryWrapper<StarCode> wrapper = new LambdaQueryWrapper<>();

        wrapper.eq(StarCode::getType,1);

        JSONArray array = new JSONArray();

        List<StarCode> codeList = codeMapper.selectList(wrapper);

        List<TreeNode> treeNodes = codeList.stream().map(code -> new TreeNode(code.getId(),code.getCodeText(),code.getFid())).collect(Collectors.toList());

        TreeNode root = new TreeNode(CommonNumberConstants.ZERO_STR,"代码管理",CommonNumberConstants.MINUS_ONE_STR);

        array.add(TreeNodeUtil.merge(root,treeNodes).toJSON());

        return array;
    }
}
